Java 深拷贝与浅拷贝
一、概念总览
1.1 三种拷贝方式对比
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#fdfdfd"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
graph TB
%% 样式定义
classDef refStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1
classDef shallowStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100
classDef deepStyle fill:#f1f8e9,stroke:#4caf50,stroke-width:2px,color:#1b5e20
classDef titleStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,color:#333,font-weight:bold
MainTitle(["Java 对象拷贝方式总览"])
subgraph SourceObject ["原始对象 A (Memory Structure)"]
A_Data["name = '张三'"]
A_Addr["address"]
Target[("Address Object: 北京")]
A_Addr -- "引用指向" --> Target
end
subgraph CopyTypes ["三种拷贝机制对比"]
direction LR
subgraph RefCopy ["引用拷贝 (Reference Copy)"]
R1["两个引用指向同一对象"]
R2["A == B (地址相同)"]
R3["修改 B 会影响 A"]
end
subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"]
S1["创建新对象 B"]
S2["基本类型拷贝值"]
S3["引用类型共享地址"]
end
subgraph DeepCopy ["深拷贝 (Deep Copy)"]
D1["完全独立的新对象"]
D2["递归拷贝所有层级"]
D3["修改 B 对 A 无影响"]
end
end
subgraph Comparison ["底层效果直观对比"]
C1["B ──┐<br/> ├─> [同一个对象] <br/>A ──┘"]
C2["B (新对象) ──> [共享 Address] <br/>A (原对象) ──> [共享 Address]"]
C3["B (新对象) ──> [新 Address] <br/>A (原对象) ──> [原 Address]"]
end
%% 连接逻辑
MainTitle --> SourceObject
SourceObject --> CopyTypes
RefCopy ==> C1
ShallowCopy ==> C2
DeepCopy ==> C3
%% 应用样式
class RefCopy,R1,R2,R3,C1 refStyle
class ShallowCopy,S1,S2,S3,C2 shallowStyle
class DeepCopy,D1,D2,D3,C3 deepStyle
class MainTitle titleStyle
class SourceObject,A_Data,A_Addr,Target titleStyle
1.2 一句话定义
| 拷贝类型 |
定义 |
修改影响 |
| 引用拷贝 |
复制引用地址,两个引用指向同一对象 |
完全影响 |
| 浅拷贝 |
创建新对象,但内部引用类型属性共享 |
部分影响 |
| 深拷贝 |
创建新对象,所有层级都是全新的 |
互不影响 |
二、引用拷贝
2.1 概念图解
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart LR
%% 样式定义
classDef stackStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1;
classDef heapStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
classDef codeStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray: 5 5,color:#333;
classDef noteStyle fill:#e8f5e9,stroke:#4caf50,stroke-width:1px,color:#1b5e20;
%% 顶部代码展示
Code["代码:Person p2 = p1;"]:::codeStyle
subgraph Memory ["内存布局 (引用拷贝)"]
direction LR
subgraph Stack ["栈内存 (Stack)"]
P1["p1 = 0x100"]:::stackStyle
P2["p2 = 0x100"]:::stackStyle
end
subgraph Heap ["堆内存 (Heap)"]
Object["<b>Person 对象</b><br/>name = '张三'<br/>age = 20<br/><i>地址: 0x100</i>"]:::heapStyle
end
%% 引用指向
P1 ==> Object
P2 ==> Object
end
%% 特点描述
Features["<b>特点说明:</b><br/>• 没有创建新对象<br/>• 两个引用指向同一个内存地址<br/>• 修改 p1 会同步反映在 p2 上"]:::noteStyle
%% 布局辅助
Code ~~~ Memory
Memory ~~~ Features
2.2 代码示例
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class ReferenceCopyDemo {
public static void main(String[] args) {
Person p1 = new Person("张三", 20);
Person p2 = p1;
System.out.println("===== 修改前 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p1 == p2: " + (p1 == p2));
p2.setAge(25);
p2.setName("李四");
System.out.println("\n===== 通过 p2 修改后 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
}
}
输出结果:
===== 修改前 =====
p1: Person{name='张三', age=20}
p2: Person{name='张三', age=20}
p1 == p2: true
===== 通过 p2 修改后 =====
p1: Person{name='李四', age=25}
p2: Person{name='李四', age=25}
三、浅拷贝
3.1 概念图解
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
graph LR
%% 定义样式
classDef main fill:
classDef storage fill:
classDef decision fill:
classDef term fill:
subgraph Stack ["栈内存 (Stack)"]
P1_Ref["p1 = 0x100"]
P2_Ref["p2 = 0x200"]
end
subgraph Heap ["堆内存 (Heap)"]
subgraph Object1 ["Person 对象 (0x100)"]
P1_Data["name: '张三'<br/>age: 20<br/>address: 0x300"]
end
subgraph Object2 ["Person 对象 (0x200)"]
P2_Data["name: '张三'<br/>age: 20<br/>address: 0x300"]
end
Addr_Obj[("Address 对象 (0x300)<br/>city: '北京'")]
end
%% 连线关系
P1_Ref ==> Object1
P2_Ref ==> Object2
P1_Data -. "引用共享" .-> Addr_Obj
P2_Data -. "引用共享" .-> Addr_Obj
%% 注释说明
Note1["<b>浅拷贝特点</b><br/>1. 创建了新对象实例<br/>2. 基本类型值复制<br/>3. 引用类型仅复制地址"]
%% 应用样式
class P1_Ref,P2_Ref main;
class Addr_Obj storage;
class Note1 term;
class Object1,Object2 decision;
%% 布局辅助
Note1 ~~~ Stack
3.2 实现方式:Cloneable 接口
public class Address {
private String city;
private String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
@Override
public String toString() {
return "Address{city='" + city + "', street='" + street + "'}";
}
}
public class Person implements Cloneable {
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";
}
}
3.3 浅拷贝测试
public class ShallowCopyDemo {
public static void main(String[] args) {
Address address = new Address("北京", "长安街");
Person p1 = new Person("张三", 20, address);
Person p2 = p1.clone();
System.out.println("===== 拷贝后初始状态 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p1 == p2: " + (p1 == p2));
System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));
p2.setAge(25);
System.out.println("\n===== 修改 p2 的 age 后 =====");
System.out.println("p1.age: " + p1.getAge());
System.out.println("p2.age: " + p2.getAge());
p2.getAddress().setCity("上海");
System.out.println("\n===== 修改 p2 的 address.city 后 =====");
System.out.println("p1.address: " + p1.getAddress());
System.out.println("p2.address: " + p2.getAddress());
p2.setAddress(new Address("广州", "天河路"));
System.out.println("\n===== 替换 p2 的整个 address 后 =====");
System.out.println("p1.address: " + p1.getAddress());
System.out.println("p2.address: " + p2.getAddress());
}
}
输出结果:
===== 拷贝后初始状态 =====
p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p1 == p2: false
p1.address == p2.address: true
===== 修改 p2 的 age 后 =====
p1.age: 20
p2.age: 25
===== 修改 p2 的 address.city 后 =====
p1.address: Address{city='上海', street='长安街'}
p2.address: Address{city='上海', street='长安街'}
===== 替换 p2 的整个 address 后 =====
p1.address: Address{city='上海', street='长安街'}
p2.address: Address{city='广州', street='天河路'}
3.4 Object.clone() 源码分析
protected native Object clone() throws CloneNotSupportedException;
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
%% 样式定义
classDef main fill:
classDef decision fill:
classDef error fill:
classDef term fill:
classDef storage fill:
Start(["开始调用 Object.clone()"]) --> CheckInterface{"是否实现<br/>Cloneable 接口?"}
%% 异常分支
CheckInterface -- 否 --> ThrowEx[/"抛出 CloneNotSupportedException"/]
class ThrowEx error
%% 正常流程
CheckInterface == 是 ==> Allocate["创建新对象<br/>(分配内存空间)"]
class Allocate main
Allocate ==> FieldCopy[["执行字段复制 (Field Copy)"]]
subgraph CopyDetail [" 字段复制机制 (浅拷贝) "]
direction TB
Primitive["基本类型<br/>(int, double, boolean...)"] -- 直接复制值 --> Value["新旧对象值相同"]
Reference["引用类型<br/>(对象、数组)"] -- 复制引用地址 --> Address["指向堆中同一个对象"]
end
FieldCopy --- CopyDetail
CopyDetail ==> Return(["返回新对象的引用"])
class Return term
%% 节点样式应用
class CheckInterface decision
class FieldCopy main
class Primitive,Reference storage
四、深拷贝
4.1 概念图解
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}
flowchart LR
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
classDef highlight fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
subgraph Stack ["栈内存 (Stack)"]
P1_Ref["p1 = 0x100"]
P2_Ref["p2 = 0x200"]
end
subgraph Heap ["堆内存 (Heap)"]
subgraph P1_Area ["原始对象 P1"]
P1_Obj["Person 对象 (0x100)<br/>name: '张三'<br/>age: 20"]
P1_Addr_Ref["address (指向 0x300)"]
end
subgraph P2_Area ["克隆对象 P2"]
P2_Obj["Person 对象 (0x200)<br/>name: '张三'<br/>age: 20"]
P2_Addr_Ref["address (指向 0x400)"]
end
Addr1[("Address 对象 (0x300)<br/>city: '北京'")]
Addr2[("Address 对象 (0x400)<br/>city: '北京'")]
end
P1_Ref ==> P1_Obj
P2_Ref ==> P2_Obj
P1_Obj --- P1_Addr_Ref
P1_Addr_Ref --> Addr1
P2_Obj --- P2_Addr_Ref
P2_Addr_Ref --> Addr2
Status{"完全独立"}
Addr1 -.-> Status
Addr2 -.-> Status
class P1_Ref,P2_Ref main;
class Addr1,Addr2 storage;
class Status highlight;
Note1["代码:Person p2 = p1.deepClone();"]
Note1 ~~~ Stack
4.2 实现方式一:手动递归拷贝
public class Address implements Cloneable {
private String city;
private String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
@Override
public Address clone() {
try {
return (Address) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
@Override
public String toString() {
return "Address{city='" + city + "', street='" + street + "'}";
}
}
public class Person implements Cloneable {
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public Person clone() {
try {
Person cloned = (Person) super.clone();
if (this.address != null) {
cloned.address = this.address.clone();
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";
}
}
4.3 深拷贝测试
public class DeepCopyDemo {
public static void main(String[] args) {
Address address = new Address("北京", "长安街");
Person p1 = new Person("张三", 20, address);
Person p2 = p1.clone();
System.out.println("===== 拷贝后初始状态 =====");
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p1 == p2: " + (p1 == p2));
System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));
p2.getAddress().setCity("上海");
System.out.println("\n===== 修改 p2 的 address.city 后 =====");
System.out.println("p1.address: " + p1.getAddress());
System.out.println("p2.address: " + p2.getAddress());
}
}
输出结果:
===== 拷贝后初始状态 =====
p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p1 == p2: false
p1.address == p2.address: false
===== 修改 p2 的 address.city 后 =====
p1.address: Address{city='北京', street='长安街'}
p2.address: Address{city='上海', street='长安街'}
4.4 实现方式二:序列化方式(推荐)
import java.io.*;
public class DeepCopyUtil {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T deepCopy(T object) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
T copy = (T) ois.readObject();
ois.close();
return copy;
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("深拷贝失败", e);
}
}
}
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
private String city;
private String street;
}
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private Address address;
}
public class SerializationDeepCopyDemo {
public static void main(String[] args) {
Address address = new Address("北京", "长安街");
Person p1 = new Person("张三", 20, address);
Person p2 = DeepCopyUtil.deepCopy(p1);
System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));
p2.getAddress().setCity("上海");
System.out.println("p1.address.city: " + p1.getAddress().getCity());
System.out.println("p2.address.city: " + p2.getAddress().getCity());
}
}
4.5 实现方式三:JSON 序列化(第三方库)
import com.google.gson.Gson;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonDeepCopy {
private static final Gson gson = new Gson();
public static <T> T deepCopy(T object, Class<T> clazz) {
String json = gson.toJson(object);
return gson.fromJson(json, clazz);
}
}
public class JacksonDeepCopy {
private static final ObjectMapper mapper = new ObjectMapper();
public static <T> T deepCopy(T object, Class<T> clazz) {
try {
String json = mapper.writeValueAsString(object);
return mapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Person p2 = JsonDeepCopy.deepCopy(p1, Person.class);
4.6 深拷贝实现方式对比
| 实现方式 |
优点 |
缺点 |
适用场景 |
| 手动递归 |
性能最好,可定制 |
代码量大,易遗漏 |
简单对象 |
| 序列化 |
通用,自动处理嵌套 |
性能较差,需实现 Serializable |
复杂对象 |
| JSON |
简单,无需特殊接口 |
性能一般,需引入依赖 |
与前端交互的对象 |
| 拷贝构造器 |
直观,可控 |
每个类都要写 |
明确需要拷贝的类 |
五、三种拷贝对比
5.1 完整对比图
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
classDef note fill:#fafafa,stroke:#9e9e9e,stroke-dasharray: 5 5;
subgraph RefCopy ["引用拷贝 (Reference Copy)"]
direction LR
R_p1["p1 (引用)"]
R_p2["p2 (引用)"]
R_Obj1[["Person 对象"]]
R_Addr1[("Address 对象")]
R_p1 --> R_Obj1
R_p2 --> R_Obj1
R_Obj1 -- "address 属性" --> R_Addr1
R_Note["✗ 没有创建新对象<br/>✗ 修改任何属性都互相影响"]
class R_Note note
end
subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"]
direction LR
S_p1["p1 (引用)"]
S_p2["p2 (引用)"]
S_Obj1[["Person 对象 (原)"]]
S_Obj2[["Person 对象 (新)"]]
S_Addr1[("Address 对象 (共享)")]
S_p1 --> S_Obj1
S_p2 --> S_Obj2
S_Obj1 -- "address" --> S_Addr1
S_Obj2 -- "address" --> S_Addr1
S_Note["✓ 创建了新 Person 对象<br/>✓ 基本类型独立<br/>✗ 引用类型属性共享"]
class S_Note note
end
subgraph DeepCopy ["深拷贝 (Deep Copy)"]
direction LR
D_p1["p1 (引用)"]
D_p2["p2 (引用)"]
D_Obj1[["Person 对象 (原)"]]
D_Obj2[["Person 对象 (新)"]]
D_Addr1[("Address 对象 (原)")]
D_Addr2[("Address 对象 (新)")]
D_p1 --> D_Obj1
D_p2 --> D_Obj2
D_Obj1 -- "address" --> D_Addr1
D_Obj2 -- "address" --> D_Addr2
D_Note["✓ 所有属性完全独立<br/>✓ 递归复制引用对象<br/>✓ 完全互不影响"]
class D_Note note
end
%% 应用样式
class R_p1,R_p2,S_p1,S_p2,D_p1,D_p2 main
class R_Obj1,S_Obj1,S_Obj2,D_Obj1,D_Obj2 decision
class R_Addr1,S_Addr1,D_Addr1,D_Addr2 storage
5.2 修改影响对比表
| 操作 |
引用拷贝 |
浅拷贝 |
深拷贝 |
| 修改 p2.age(基本类型) |
p1 受影响 |
p1 不受影响 |
p1 不受影响 |
| 修改 p2.name(String,不可变) |
p1 受影响 |
p1 不受影响* |
p1 不受影响 |
| 修改 p2.address.city |
p1 受影响 |
p1 受影响 |
p1 不受影响 |
| 替换 p2.address = new Address() |
p1 受影响 |
p1 不受影响 |
p1 不受影响 |
*注:String 是不可变对象,重新赋值会创建新对象,所以表现得像深拷贝。
5.3 综合测试代码
public class CopyComparisonDemo {
public static void main(String[] args) {
System.out.println("========== 1. 引用拷贝 ==========");
testReferenceCopy();
System.out.println("\n========== 2. 浅拷贝 ==========");
testShallowCopy();
System.out.println("\n========== 3. 深拷贝 ==========");
testDeepCopy();
}
static void testReferenceCopy() {
Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
Person p2 = p1;
p2.getAddress().setCity("上海");
System.out.println("修改 p2.address.city 后:");
System.out.println("p1.address.city = " + p1.getAddress().getCity());
System.out.println("p2.address.city = " + p2.getAddress().getCity());
System.out.println("结论: p1 受影响");
}
static void testShallowCopy() {
Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
Person p2 = p1.shallowClone();
p2.getAddress().setCity("上海");
System.out.println("修改 p2.address.city 后:");
System.out.println("p1.address.city = " + p1.getAddress().getCity());
System.out.println("p2.address.city = " + p2.getAddress().getCity());
System.out.println("结论: p1 受影响(共享内部对象)");
}
static void testDeepCopy() {
Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
Person p2 = p1.deepClone();
p2.getAddress().setCity("上海");
System.out.println("修改 p2.address.city 后:");
System.out.println("p1.address.city = " + p1.getAddress().getCity());
System.out.println("p2.address.city = " + p2.getAddress().getCity());
System.out.println("结论: p1 不受影响(完全独立)");
}
}
六、复杂场景:多层嵌套
6.1 多层嵌套对象
public class Company implements Serializable, Cloneable {
private String name;
private Address headquarters;
private List<Department> departments;
@Override
public Company clone() {
try {
Company cloned = (Company) super.clone();
if (this.headquarters != null) {
cloned.headquarters = this.headquarters.clone();
}
if (this.departments != null) {
cloned.departments = new ArrayList<>();
for (Department dept : this.departments) {
cloned.departments.add(dept.clone());
}
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
public class Department implements Serializable, Cloneable {
private String name;
private List<Employee> employees;
@Override
public Department clone() {
try {
Department cloned = (Department) super.clone();
if (this.employees != null) {
cloned.employees = new ArrayList<>();
for (Employee emp : this.employees) {
cloned.employees.add(emp.clone());
}
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
6.2 多层嵌套图示
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
subgraph ShallowCopy ["浅拷贝 (Shallow Copy) - 仅复制顶层"]
direction LR
S_Orig["原对象 Company"]
S_Addr["Address 对象"]
S_List["List 集合"]
S_Dept["Department 对象"]
S_Emp["Employee 对象"]
S_New["新对象 Company"]
S_Orig --> S_Addr
S_Orig --> S_List
S_List --> S_Dept
S_Dept --> S_Emp
S_New == "引用相同地址" ==> S_Addr
S_New == "引用相同地址" ==> S_List
end
subgraph DeepCopy ["深拷贝 (Deep Copy) - 递归复制所有层级"]
direction TB
subgraph OriginalTree ["原始对象树"]
direction LR
O_Comp["Company"] --> O_Addr["Address"]
O_Addr --> O_List["List"]
O_List --> O_Dept["Department"]
O_Dept --> O_Emp["Employee"]
end
subgraph NewTree ["全新副本树"]
direction LR
N_Comp["Company"] --> N_Addr["Address"]
N_Addr --> N_List["List"]
N_List --> N_Dept["Department"]
N_Dept --> N_Emp["Employee"]
end
O_Comp -. "独立副本" .-> N_Comp
O_Addr -. "独立副本" .-> N_Addr
O_List -. "独立副本" .-> N_List
O_Dept -. "独立副本" .-> N_Dept
O_Emp -. "独立副本" .-> N_Emp
end
subgraph Tips ["💡 最佳实践"]
T1["复杂对象推荐使用序列化/反序列化 (JSON/Protobuf)"]
T2["手动实现需注意循环引用问题"]
end
%% 样式定义
classDef main fill:
classDef decision fill:
classDef term fill:
classDef storage fill:
class S_New,N_Comp,N_Addr,N_List,N_Dept,N_Emp main;
class S_Orig,O_Comp,O_Addr,O_List,O_Dept,O_Emp storage;
class T1,T2 decision;
七、特殊情况处理
7.1 不可变对象
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
subgraph Core ["不可变对象核心逻辑"]
direction TB
ObjType(["不可变对象 (Immutable Objects)"])
Examples["String, Integer, LocalDate"]
Features{{"核心特点"}}
F1["创建后状态不可改变"]
F2["修改操作 = 返回新对象"]
Strategy{{"拷贝处理策略"}}
S1["直接引用共享 (Shallow Share)"]
S2["无需深拷贝 (Deep Copy Not Needed)"]
end
subgraph Example ["内存变化示例: String name = '张三'"]
direction LR
State1["栈变量: name"] -- "初始指向" --> Val1[("堆内存: '张三'")]
Update["执行: name = '李四'"]
State1 == "重定向" ==> Val2[("堆内存: '李四'")]
Val1 -. "原对象保持不变" .-> Val1
end
%% 节点连接
ObjType --- Examples
Examples --> Features
Features --> F1
Features --> F2
F1 & F2 --> Strategy
Strategy --> S1
Strategy --> S2
S1 ==> Example
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
class ObjType,Examples main;
class Features,Strategy decision;
class F1,F2,S1,S2 term;
class Val1,Val2 storage;
7.2 数组的拷贝
public class ArrayCopyDemo {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1.clone();
arr2[0] = 100;
System.out.println(arr1[0]);
Person[] persons1 = {new Person("张三", 20, null)};
Person[] persons2 = persons1.clone();
persons2[0].setName("李四");
System.out.println(persons1[0].getName());
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = matrix1.clone();
matrix2[0][0] = 100;
System.out.println(matrix1[0][0]);
int[][] matrix3 = new int[matrix1.length][];
for (int i = 0; i < matrix1.length; i++) {
matrix3[i] = matrix1[i].clone();
}
}
}
数组拷贝总结:
| 数组类型 |
clone() / Arrays.copyOf() |
效果 |
| 一维基本类型 |
深拷贝 |
✅ 独立 |
| 一维引用类型 |
浅拷贝 |
⚠️ 元素共享 |
| 二维数组 |
浅拷贝 |
⚠️ 行数组共享 |
八、最佳实践与总结
8.1 选择建议
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
graph TB
%% 样式定义
classDef main fill:
classDef decision fill:
classDef term fill:
classDef highlight fill:
subgraph SelectionGuide ["对象拷贝选择建议"]
direction TB
Start(["开始判断"]) --> Q1{"需要拷贝对象吗?"}
Q1 -- "只读使用" --> Result1["引用拷贝<br/>(无需物理拷贝)"]
Q1 -- "需要修改" --> Q2{"对象包含引用属性?"}
Q2 -- "没有" --> Result2["浅拷贝<br/>(Shallow Copy)"]
Q2 -- "有" --> Q3{"内部引用也需要<br/>独立修改吗?"}
Q3 -- "否" --> Result3["浅拷贝"]
Q3 -- "是" --> Result4["深拷贝<br/>(Deep Copy)"]
end
%% 节点分类应用
class Start main;
class Q1,Q2,Q3 decision;
class Result1,Result2,Result3 term;
class Result4 highlight;
%% 核心路径加粗
Q2 == "有" ==> Q3
Q3 == "是" ==> Result4
%% 补充说明样式
style SelectionGuide fill:
8.2 实现方式选择
| 场景 |
推荐方式 |
原因 |
| 简单对象,无嵌套 |
手动 clone |
性能最好 |
| 复杂对象,多层嵌套 |
序列化 |
自动处理所有层级 |
| 需要与前端交互 |
JSON |
一举两得 |
| 防御性拷贝 |
拷贝构造器 |
代码直观 |
| 集合拷贝 |
Stream + 深拷贝 |
灵活控制 |
8.3 防御性拷贝
public class ImmutablePerson {
private final String name;
private final Date birthDate;
public ImmutablePerson(String name, Date birthDate) {
this.name = name;
this.birthDate = new Date(birthDate.getTime());
}
public Date getBirthDate() {
return new Date(birthDate.getTime());
}
}
8.4 速查表
| 对比项 |
引用拷贝 |
浅拷贝 |
深拷贝 |
| 新对象 |
❌ |
✅ |
✅ |
| 基本类型独立 |
❌ |
✅ |
✅ |
| 引用类型独立 |
❌ |
❌ |
✅ |
| 实现难度 |
无 |
简单 |
复杂 |
| 性能 |
最快 |
快 |
较慢 |
8.5 记忆口诀
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#f5f5f5"
},
"flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%
flowchart TB
%% 核心分类
Root(["Java/JS 对象拷贝记忆口诀"])
subgraph RefGroup ["引用拷贝 (Reference Copy)"]
direction TB
R1["复制地址,同一对象"]
R2[["两个名字,一个人"]]
end
subgraph ShallowGroup ["浅拷贝 (Shallow Copy)"]
direction TB
S1["新皮旧馅,表面功夫"]
S2["房子是新的,家具是共享的"]
S3["基本类型复制值,引用类型复制地址"]
end
subgraph DeepGroup ["深拷贝 (Deep Copy)"]
direction TB
D1["彻底独立,完全分家"]
D2["房子是新的,家具也全是新的"]
D3["递归复制,层层独立"]
end
subgraph StrategyGroup ["选择口诀 (Strategy)"]
direction LR
ST1["只读引用,修改要拷贝"]
ST2["简单浅拷贝,嵌套深拷贝"]
ST3["序列化最省心,手动写最性能"]
end
%% 连接关系
Root ==> RefGroup
Root ==> ShallowGroup
Root ==> DeepGroup
RefGroup ~~~ StrategyGroup
ShallowGroup ==> StrategyGroup
DeepGroup ==> StrategyGroup
%% 样式定义
classDef main fill:
classDef decision fill:
classDef term fill:
classDef storage fill:
class Root main;
class R1,R2 main;
class S1,S2,S3 decision;
class D1,D2,D3 term;
class ST1,ST2,ST3 storage;
8.6 核心要点图
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#e3f2fd",
"primaryTextColor": "#0d47a1",
"primaryBorderColor": "#2196f3",
"lineColor": "#546e7a",
"fontSize": "14px",
"tertiaryColor": "#fdfdfd"
},
"flowchart": { "curve": "basis", "htmlLabels": true }
}}%%
graph TB
%% 核心分类
subgraph Core ["1. 本质区别 (Copy Types)"]
Type1["<b>引用拷贝</b><br/>仅复制指针,指向同一内存地址"]
Type2["<b>浅拷贝</b><br/>创建新对象,但内部引用仍共享"]
Type3["<b>深拷贝</b><br/>递归复制,完全独立的副本"]
end
%% 实现路径
subgraph Implementation ["2. 实现方式 (Implementation)"]
direction LR
Method1[["Object.clone() 默认方式"]]
subgraph DeepMethods ["深拷贝具体手段"]
M2["手动递归 Clone"]
M3["序列化 / 反序列化"]
M4["JSON 转换"]
M5["拷贝构造器"]
end
end
%% 注意事项
subgraph Precautions ["3. 开发注意事项 (Best Practices)"]
Note1("必须实现 Cloneable 接口")
Note2("String 等不可变对象无需深拷贝")
Note3("数组 clone 对引用元素仍是浅拷贝")
Note4("复杂对象推荐序列化方式")
end
%% 逻辑连接
Type2 -.-> Method1
Type3 -.-> DeepMethods
Method1 ==> Note1
DeepMethods ==> Note4
%% 样式定义
classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
class Type1,Type2,Type3 main;
class Method1,M2,M3,M4,M5 decision;
class Note1,Note2,Note3,Note4 term;
💬 评论